package com.lovegu.netty.coder;

import com.lovegu.netty.serialize.Serializer;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import lombok.AllArgsConstructor;

import java.util.List;

/**
 * @author 老顾 1437594522@qq.com
 * @description kryo序列化，自定义解码器
 * @date 2022/11/23 8:25
 */
@AllArgsConstructor
public class NettyKryoDecoder extends ByteToMessageDecoder {

    private final Serializer serializer;
    private final Class<?> genericClass;

    /**
     * Netty传输的消息长度，也就是对象序列化后对应的字节数组的大小，存储在ByteBuf头部
     */
    private static final int BODY_LENGTH = 4;

    /**
     * 解码 ByteBuf 对象
     * @param channelHandlerContext
     * @param byteBuf
     * @param list
     * @throws Exception
     */
    @Override
    protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
        //1.byteBuf中写入的消息长度所占的字节数已经是4了，所以byteBuf的可读字节必须大于4
        if (internalBuffer().readableBytes() >= BODY_LENGTH) {
            //2.标记当前readIndex的位置，以便后面重置readIndex的时候使用
            internalBuffer().markReaderIndex();
            //3.读取消息的长度
            //注意：消息长度是encode的时候我们字节写入的
            int dataLength = internalBuffer().readInt();
            //4.遇到不合理的情况直接return
            if (dataLength < 0 || internalBuffer().readableBytes() < 0){
                System.out.println("数据长度或者字节缓冲区的可读字节数不可用");
            }
            //5.如果可读字节数小于消息长度的话，说明是不完整的消息，重置readIndex
            if (internalBuffer().readableBytes() < dataLength) {
                internalBuffer().resetReaderIndex();
            }
            //6.到这里说明没什么问题了，可以序列合了
            byte[] body = new byte[dataLength];
            internalBuffer().readBytes(body);
            //将bytes数组转换为我们需要的对象
            Object obj = serializer.deserialize(body,genericClass);
            list.add(obj);
            System.out.println("成功反序列化对象");
        }
    }
}
